import { ServerVo } from "./ServerVo";
import { LZString } from "../../app_cocos/libs/lz-string";
import { app } from "../../base";
import { Handler } from "../../app_base/base/utils/Handler";
import { G_Data } from "../DataCenter";
import { Link } from "../../app_base/module/structure/Link";

export let ServerConfig = {
    domain: "",
    configAPI: "",
    saveStoreAPI: "",
    getStoreAPI: "",
    loginAPI: "",
}
/**
 @name: IServer
 @desc: 服务器数据
 @author: timoo
 @date: 2022/11/30
 */
export class Server {
    private _vo: ServerVo;
    private _serverTime: number;
    private _startedAppTime: number;
    private _lastSaveUserTime: number = 0;

    init(): Server {
        if (!this._vo) {
            this._vo = new ServerVo();
        }
        return this;
    }

    public set time(time: number) {
        this._serverTime = time;
        this._startedAppTime = Date.now();
        console.log("更新服务器时间：", time);
    }

    /**
     * 服务器时间戳 毫秒
     */
    public get time(): number {
        if (this._serverTime) {
            return this._serverTime + Date.now() - this._startedAppTime;
        }
        return Date.now();
    }

    /**
     * 服务器日期对象
     */
    public get date(): Date {
        return new Date(this.time)
    }

    /**
     * 服务器配置数据
     */
    public get data(): ServerVo {
        return this._vo;
    }

    public requestConfig(): Promise<void> {
        return new Promise((resolve) => {
            app.net.http.get(
                ServerConfig.domain + ServerConfig.configAPI,
                {
                    responseType: "json",
                    data: this._getConfigParams(),
                    onComplete: Handler.create(this, (data) => {
                        console.log(`[S=>C](${ServerConfig.configAPI} ${JSON.stringify(data)})=>`)
                        if (data && data.data && data.data.timestamps) {
                            let time = Number(data.data.timestamps);
                            if (!Number.isNaN(time)) {
                                this.time = time;
                            }
                        }
                        if (data && data.data && data.code == "200" && data.msg == "success") {
                            // this._updateConfig(data.data);
                            resolve();
                            return;
                        }
                        // this._updateConfig();
                        resolve();
                    }),
                    onError: Handler.create(this, () => {
                        // this._updateConfig();
                        resolve();
                    })
                })
        });
    }

    private _getConfigParams(): object {
        return {
            userId: app.publisher.login.openID,
            gameCode: app.publisher.publisher.gameCode,
            gameChannel: app.publisher.publisher.channelType,
        }
    }

    private _updateConfig(data?: { global: any, extra: any, version: string }): void {
        data = data || app.storage.getGValue("ServerData", { global: {}, extra: {}, version: app.publisher.appVersion });
        for (const key in data.global) {
            if (Object.prototype.hasOwnProperty.call(data.global, key)) {
                let value = data.global[key];
                this._vo[key] = value;
            }
        }

        if (data.version == app.publisher.appVersion) {
            for (const key in data.extra) {
                if (Object.prototype.hasOwnProperty.call(data.extra, key)) {
                    let value = data.extra[key];
                    if (data.global[key]) {
                        console.warn(`警告：版本[${data.version}]配置${key}:${value} 覆盖全局配置${key}:${data.global[key]}`)
                    }
                    this._vo[key] = value;
                }
            }
        }

        //根据特殊字段bundle设置bundle版本
        const bundleVersion = this._vo['bundle'];
        if (bundleVersion) {
            let map: Map<string, string> = new Map();
            for (const bundleName in bundleVersion) {
                if (Object.prototype.hasOwnProperty.call(bundleVersion, bundleName)) {
                    const version = bundleVersion[bundleName];
                    map.set(bundleName, version);
                }
            }
            app.res.setBundleVersion(map);
        }

        app.storage.setGValue("ServerData", this._vo.toString());
    }

    /**
  * 保存用户数据
  * @param data 
  * @returns 
  */
    public saveUserData<T>(data: Link<T>): Promise<boolean> {
        return this._saveUserData(data.toObject())
    }

    printTime(time) {
        //时间戳转换年月日时分秒
        let date = new Date(time);
        let year = date.getFullYear();
        let month = date.getMonth() + 1;
        let day = date.getDate();
        let hour = date.getHours();
        let minute = date.getMinutes();
        let second = date.getSeconds();
        return "当前时间：" + year + "年" + month + "月" + day + "日" + hour + "时" + minute + "分" + second + "秒"
    }

    private _saveUserData(data: any): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            if (cc.sys.isBrowser || CC_DEBUG) { return resolve(false); }
            if (!data) {
                resolve(false);
                return
            }
            if (!app.storage.userId || !app.publisher.appId) {
                resolve(false);
                return
            }
            // console.log("当前数据保存时间:", this.printTime(this.time), this.time - this._lastSaveUserTime)
            // console.log("上次数据保存时间:", this.printTime(this._lastSaveUserTime), this.time - this._lastSaveUserTime)
            if (this.time - this._lastSaveUserTime < this._vo.savecd) {
                console.log("保存数据CD中，跳过保存");
                resolve(false);
                return;
            }

            app.net.http.post(
                ServerConfig.domain + ServerConfig.saveStoreAPI,
                {
                    responseType: "json",
                    data: { userId: app.publisher.appId + "_" + app.storage.userId, gameData: JSON.stringify(data) },
                    onComplete: Handler.create(this, (result: { code: number, msg: string, timestamp: number }) => {
                        console.log("[saveUserData] complete", JSON.stringify(result), data);
                        this._lastSaveUserTime = this.time;
                        if (result && result.code == 200) {
                            // console.log("更新数据保存时间:", this.printTime(this.time))
                            resolve(true);
                        } else {
                            console.error("[saveUserData] server error", JSON.stringify(result));
                            resolve(false);
                        }
                    }),
                    onError: Handler.create(this, (error) => {
                        console.error("[saveUserData] error", JSON.stringify(error));
                        resolve(false);
                    })
                }
            );
        })
    }

    public getUserData(): Promise<any> {
        return new Promise((resolve) => {
            if (!app.storage.userId || !app.publisher.appId) {
                resolve(null);
                return
            }
            app.net.http.get(
                ServerConfig.domain + ServerConfig.getStoreAPI,
                {
                    responseType: "json", timeout: 2000, retryTimes: 1,
                    data: {
                        userId: app.publisher.appId + "_" + app.storage.userId,
                        gameCode: "",
                        gameChannel: "",
                    },
                    onComplete: Handler.create(this, (result: { code: number, msg: string, timestamp: number, data: any }) => {
                        console.log("[getUserData] complete", JSON.stringify(result));
                        if (result && result.code == 200) {
                            let data = {}
                            if (result.data && result.data.gameData) {
                                data = JSON.parse(result.data.gameData);
                            }
                            resolve(data);
                        } else {
                            console.error("[getUserData] server error", JSON.stringify(result));
                            resolve(null);
                        }
                    }),
                    onError: Handler.create(this, (error) => {
                        console.error("[getUserData] error", JSON.stringify(error));
                        resolve(null);
                    }),
                    // jsonReviver: app.Json.TimestampReviver
                }
            );
        });
    }
}